var GalleryViewer = {
    initialized:       false, //boolean to determine if init() has been run yet
    /*
     * Nodes
     */
    ajaxNode:          null, //ajax data destination
    prevLinkNode:      null, //node for link to previous image
    nextLinkNode:      null, //node for link to next image
    filmStripCache:    [], //array to cache film strip responses
    tempKeywords:      "", //temporary keywords (not applied until hit 'apply')
    keywords:          "", //list of keywords for filtering
    currentId:         "",
    galleryType:       "images",  // can be images or videos
    dataKey:           null, //data key for ajax call
    thumbnailPageCache: [], //array to cache thumbnail pages
    currentThumbnailPage: 1,
    /*
     * Constants
     */
    THUMBNAIL_HOLDER_WIDTH: 910, //total width of thumbnail container
    THUMBNAIL_WIDTH:   130, //total width including borders, margin, and padding
    AJAX_CONTAINER_ID: "#item-viewer",
    PREV_LINK_ID:      "#previous-item",
    NEXT_LINK_ID:      "#next-item",
    THUMBNAIL_LIST_ID: "#media-thumbnails .thumbnail-link",
    AJAX_URL:          "media/item",
    PAGING_NODE:       "#thumbnail-page",
    /*
     * Initializes the image viewer class, caches necessary data
     */
    init: function() {

        //cache prev/next link elements
        GalleryViewer.nextLinkNode = $(GalleryViewer.NEXT_LINK_ID)
        GalleryViewer.prevLinkNode = $(GalleryViewer.PREV_LINK_ID)

        //bind hover

        //store data key
        if (dataKey)
            GalleryViewer.dataKey = dataKey;

        if (!GalleryViewer.commentsNode) {
            GalleryViewer.commentsNode = $("#media-comments");
        }

        if (!GalleryViewer.loadCommentCache)
            GalleryViewer.loadCommentCache = GalleryViewer.commentsNode.html();

        //cache thumbnail nodes (link and img)
        var tempNodeList = [];
        var tempImageList = [];

        try {
            var indicesLength = indices.length;
            for (var x = 0; x < indicesLength; x++) {
                tempNodeList[x] = $("#" + indices[x]);
                tempImageList[x] = tempNodeList[x].find("span");
            }
        } catch(e) { }

        GalleryViewer.thumbnailLinkNodes = tempNodeList;
        GalleryViewer.thumbnailImageNodes = tempImageList;

        GalleryViewer.initialized = true;
    },
    /*
     * Load item based on its id and the gallery type
     */
    loadItem: function(nodeId) {

        if (!GalleryViewer.initialized) {
            GalleryViewer.init();
        }

        if (!GalleryViewer.dataKey) {
            return;
        }

        var oldIndex = (GalleryViewer.currentId == "") ? 0 : GalleryViewer.getIndex(GalleryViewer.currentId);
        var newIndex = GalleryViewer.getIndex(nodeId);

        if (oldIndex != newIndex) {

            //set hash for bookmarking goodness
            location.hash = "/" + nodeId;
            GalleryViewer.currentId = nodeId;

            //set new active thumbnail
            GalleryViewer.thumbnailLinkNodes[oldIndex].removeClass("active");
            GalleryViewer.thumbnailLinkNodes[newIndex].addClass("active");

            //check to see if selected image is off the scroll bar
            if (HSlider && HSlider.scrollPane)
                GalleryViewer.nudgeScrollContent((newIndex + 1) * GalleryViewer.THUMBNAIL_WIDTH, oldIndex, newIndex, GalleryViewer.THUMBNAIL_WIDTH);

            //load cached version
            if (GalleryViewer.filmStripCache[nodeId]) {
                GalleryViewer.ajaxNode.html(GalleryViewer.filmStripCache[nodeId]);

                //preload next/previous image
                if (oldIndex < newIndex) {
                    var preloadIndex = GalleryViewer.getNextIndex(newIndex);
                    GalleryViewer.preloadItem(preloadIndex, function() {
                        GalleryViewer.preloadItem(GalleryViewer.getNextIndex(preloadIndex))
                    });
                } else {
                    var preloadIndex = GalleryViewer.getPreviousIndex(newIndex);
                    GalleryViewer.preloadItem(preloadIndex, function() {
                        GalleryViewer.preloadItem(GalleryViewer.getPreviousIndex(preloadIndex))
                    });
                }
            } else {
              //fetch data
                $.ajax({
                    type: "GET",
                    url: Core.baseUrl + "/" + GalleryViewer.AJAX_URL,
                    data: ( { id: nodeId, dataKey: GalleryViewer.dataKey } ),
                    dataType: "html",
                    success: function(msg) {
                        if (!GalleryViewer.ajaxNode) {
                            GalleryViewer.ajaxNode = $(GalleryViewer.AJAX_CONTAINER_ID);
                        }
                        if (GalleryViewer.galleryType == "videos" && Core.isIE()) {
                            swfobject.removeSWF("flash-video");

                            var newDiv = document.createElement("div");
                            newDiv.id = "flash-video";

                            $("#flash-container").html(newDiv);
                        }

                        GalleryViewer.ajaxNode.html(msg);

                        //cache
                        GalleryViewer.filmStripCache[nodeId] = msg;

                        //preload next/previous image
                        if (oldIndex < newIndex) {
                            var preloadIndex = GalleryViewer.getNextIndex(newIndex);
                            GalleryViewer.preloadItem(preloadIndex, function() {
                                GalleryViewer.preloadItem(GalleryViewer.getNextIndex(preloadIndex))
                            });
                        } else {
                            var preloadIndex = GalleryViewer.getPreviousIndex(newIndex);
                            GalleryViewer.preloadItem(preloadIndex, function() {
                                GalleryViewer.preloadItem(GalleryViewer.getPreviousIndex(preloadIndex))
                            });
                        }

                    },
                    error: function(msg) {
                        //GalleryViewer.metaData.innerHTML = "Error loading " + nodeId + " :(";
                    }
                });
            }
        }
    },
    preloadItem: function(nodeId, callback) {

        if (!GalleryViewer.filmStripCache[nodeId]) {

            $.ajax({
                type: "GET",
                url: Core.baseUrl + "/" + GalleryViewer.AJAX_URL,
                data: ( { id: nodeId, dataKey: GalleryViewer.dataKey } ),
                dataType: "html",
                success: function(msg) {
                    //cache
                    GalleryViewer.filmStripCache[nodeId] = msg;

                    if (Core.isCallback(callback)) {
                        callback();
                    }
                }
            });
        } else {
            if (Core.isCallback(callback)) {
                callback();
            }
        }

        //return the node that was preloaded
        return nodeId;
    },
    /*
     * Custom index function for faster look up
     */
    getIndex: function(id) {
        var indicesLength = indices.length;
        var index = indicesLength-1;

        if (index >= 0 && id != "") {
            do {
                if (indices[index] == id) {
                    return index;
                }
            }
            while (index--)
        }

        return 0;
    },
    /*
     * Get next item based on item type
     */
    getNextItem: function(id) {
        if (id && id != "") {
            GalleryViewer.loadItem(id);
        } else {
            if (GalleryViewer.currentId == "")
                GalleryViewer.currentId = indices[0];

            GalleryViewer.loadItem(GalleryViewer.getNextIndex(GalleryViewer.getIndex(GalleryViewer.currentId)));
        }
    },
    /*
     * Get previous item based on item type
     */
    getPreviousItem: function(id) {
        if (GalleryViewer.currentId == "")
            GalleryViewer.currentId = indices[0];

        GalleryViewer.loadItem(GalleryViewer.getPreviousIndex(GalleryViewer.getIndex(GalleryViewer.currentId)));
    },
    getNextIndex: function(index) {
        return indices[((index + 1 == indices.length) ? 0 : index + 1)];
    },
    //store previous index
    getPreviousIndex: function(index) {
        return indices[((index > 0) ? index - 1 : indices.length - 1)];
    },
    getNextPage: function() {

        if (location.hash && location.hash != "") {
            var page = location.hash.substring(2) * 1;

            if (page + 1 > numThumbnailPages)
                GalleryViewer.loadPage(1)
            else
                GalleryViewer.loadPage(page + 1)
        } else if (numThumbnailPages >= 2) {
            GalleryViewer.loadPage(2);
        }
    },
    getPreviousPage: function() {
        if (location.hash && location.hash != "") {
            var page = location.hash.substring(2) * 1;

            if (page > 1)
                GalleryViewer.loadPage(page - 1)
            else
                GalleryViewer.loadPage(numThumbnailPages)
        } else {
            GalleryViewer.loadPage(numThumbnailPages)
        }
    },
    loadPage: function(page) {
        if (!GalleryViewer.initialized) {
            GalleryViewer.init();
        }

        if (!GalleryViewer.dataKey) {
            return;
        }

        if (!GalleryViewer.thumbnailPageNode) {
            GalleryViewer.thumbnailPageNode = $(GalleryViewer.PAGING_NODE);
        }

        GalleryViewer.currentThumbnailPage = page;

        location.hash = "/" + page;

        if (GalleryViewer.thumbnailPageCache[page]) {
            GalleryViewer.thumbnailPageNode.html(GalleryViewer.thumbnailPageCache[page]);
        } else {

            //get data
            $.ajax({
                type: "GET",
                url: Core.baseUrl + "/media/thumbnail-page",
                data: ( { page: page, dataKey: dataKey, keywords: thumbnailKeywordParams } ),
                dataType: "html",
                success: function(msg) {
                    GalleryViewer.thumbnailPageNode.html(msg);
                    GalleryViewer.handleLoadPage(page);
                },
                error: function(msg) {
                    GalleryViewer.thumbnailPageNode.html("Error loading page " + page + ".");
                }
            });
        }
    },
    handleLoadPage: function(page) {
        if (!GalleryViewer.initialized) {
            GalleryViewer.init();
        }

        if (!GalleryViewer.thumbnailPageNode) {
            GalleryViewer.thumbnailPageNode = $(GalleryViewer.PAGING_NODE);
        }

        GalleryViewer.remainingImagesToLoad = $(".index-thumb", GalleryViewer.thumbnailPageNode).length;

        $(".thumbnail-loader", GalleryViewer.thumbnailPageNode).each(function(i) {
            var thumbNode = this;
            var imgSrc = $(".thumb-frame", thumbNode).html();
            imgSrc = imgSrc.split(" ")[1];

            //load images
            var tempImage = new Image();
            tempImage.src = imgSrc;
            setTimeout(function() { GalleryViewer.loadThumbnailPageFrame(tempImage, imgSrc, $(thumbNode), page || 1)  }, 100);
        });
    },
    loadThumbnailPageFrame: function(image, src, target, page) {
        if (image.complete) {
            GalleryViewer.setImageBackground(src, target);
            GalleryViewer.remainingImagesToLoad--;

            if (GalleryViewer.remainingImagesToLoad == 0 && GalleryViewer.currentThumbnailPage == page) {
                GalleryViewer.thumbnailPageCache[page] = GalleryViewer.thumbnailPageNode.html();
            }
        } else {
            setTimeout(function() { GalleryViewer.loadThumbnailPageFrame(image, src, target, page)  }, 100)
        }

    },
    nudgeScrollContent: function(margin, oldIndex, newIndex, imageSize) {
        var scrollPaneWidth = HSlider.scrollPane.width();

        var currentMargin = parseInt(HSlider.scrollContent.css('margin-left'));

        //moving forward
        if (oldIndex < newIndex) {
            if (margin > scrollPaneWidth) {
                var newMargin = scrollPaneWidth - margin;

                if (currentMargin > newMargin) {
                    HSlider.scrollContent.css('margin-left', newMargin + 'px');
                    GalleryViewer.getViewableRange(Math.abs(newMargin));
                    HSlider.resetValue();
                }
            }
        }
        //moving backwards
        else {
            margin = margin - imageSize;
            currentMargin = Math.abs(currentMargin);

            if (currentMargin > margin) {
                HSlider.scrollContent.css('margin-left', (margin * -1) + 'px');
                GalleryViewer.getViewableRange(Math.abs(margin));
                HSlider.resetValue();
            }
        }
    },
    prepareKeywords: function(triggerNode, activeClass, targetPath) {
        //set call back for this dropdown
        Toggle.callback = GalleryViewer.cancelFilter;

        //fetch keywords from DOM (TODO: make better)
        if (GalleryViewer.keywords == "") {
            var keywordData = document.getElementById("keyword-list");
            if (keywordData)
                GalleryViewer.keywords = keywordData.innerHTML;
        }

        //assign temporary keywords
        GalleryViewer.tempKeywords = GalleryViewer.keywords;

        //trigger the open
        Toggle.open(triggerNode, activeClass, targetPath);
    },
    buildKeywords: function(node, keyword) {
        if (GalleryViewer.tempKeywords.indexOf(keyword + ",") == -1) {
            GalleryViewer.tempKeywords += keyword + ",";
            node.className = "keyword-filter checked";
        } else {
            GalleryViewer.tempKeywords = GalleryViewer.tempKeywords.replace(keyword + ",", "");
            node.className = "keyword-filter";
        }
    },
    /*
     * Join keyworks and refresh page with new urls
     */
    applyKeywordFilter: function(onFilmStripView) {
        GalleryViewer.keywords = GalleryViewer.tempKeywords;

        var urlPrepend = "?";

        if (typeof onFilmStripView == "boolean" && onFilmStripView) {
            urlPrepend = "?view=&";
        }

        if (GalleryViewer.keywords != "") {
            location.href = urlPrepend + "keywords=" + GalleryViewer.keywords.substring(0, GalleryViewer.keywords.length - 1);
        } else {
            location.href = location.pathname + (urlPrepend == "?" ? "" : urlPrepend);
        }
    },
    /*
     * Cancels the selected filters and resets back
     */
    cancelFilter: function() {

        //close element
        document.getElementById("filter-options").style.display = "none";

        $("#filter-options .keyword-filter").each(function(){

            var id = this.id.split("-")[1];

            if (GalleryViewer.keywords.indexOf(id) == -1) {
                this.className = "keyword-filter";
            } else {
                this.className = "keyword-filter checked";
            }
        });
    },
    getViewableRange: function(marginLeft) {
        if (!GalleryViewer.initialized) {
            GalleryViewer.init();
        }

        if (!marginLeft)
            var marginLeft = Math.abs(parseInt(HSlider.scrollContent.css("margin-left")));

        var minThumbnailIndex = Math.floor(marginLeft / GalleryViewer.THUMBNAIL_WIDTH);
        var maxThumbnailIndex = Math.floor((marginLeft + GalleryViewer.THUMBNAIL_HOLDER_WIDTH) / GalleryViewer.THUMBNAIL_WIDTH);

        //make sure index doesn't go above max range
        if (maxThumbnailIndex >= indices.length)
            maxThumbnailIndex = indices.length - 1;

        for (var x = minThumbnailIndex; x <= maxThumbnailIndex; x++) {
            if (GalleryViewer.thumbnailLinkNodes[x].hasClass("thumbnail-loader")) {
                var bg = GalleryViewer.thumbnailImageNodes[x].html();

                GalleryViewer.setImageBackground(bg.split(" ")[1], GalleryViewer.thumbnailLinkNodes[x]);
            }
        }
    },
    setImageBackground: function(src, target) {
        target.css("background-image", "url(' " + src + "')").removeClass("thumbnail-loader");
    },
    loadComments: function(nodeId) {
        if (!GalleryViewer.initialized) {
            GalleryViewer.init();
        }

        if (!nodeId)
            nodeId = (GalleryViewer.currentId != "" ) ? GalleryViewer.currentId : indices[0];

        //set comments node back to 'Loading comments...'
        GalleryViewer.commentsNode.html(GalleryViewer.loadCommentCache);

        //generate no cache string if needed
        var noCache = (Core.isIE()) ? new Date().getTime() : "";

        //check for keywords
        var keywordData = document.getElementById("keyword-list");
        if (keywordData) {
            GalleryViewer.keywords = keywordData.innerHTML;
        }

        var keywordsData = (GalleryViewer.keywords != "") ? GalleryViewer.keywords.substring(0, GalleryViewer.keywords.length - 1) : "";

        //discussionSig set in image-preview.ftl
        $.ajax({
            type: "GET",
            url: Core.baseUrl + "/media/comments",
            data: ( { id: nodeId, dataKey: GalleryViewer.dataKey, discussionSig: discussionSig, noCache: noCache, keywords: keywordsData  } ),
            dataType: "html",
            success: function(msg) {
                GalleryViewer.commentsNode.html(msg);
            },
            error: function(msg) {
                GalleryViewer.commentsNode.html($("#comments-error-retry").html());
            }
        });
    }
};


//if there is a hash, load from images
$(function() {

    //set custom gallery type if needed
    if (galleryType)
        GalleryViewer.galleryType = galleryType;

    if (location.hash && location.hash != "") {
        //trim off the #/
        var currentImage = location.hash.substring(2);

        if (GalleryViewer.getIndex(currentImage)) {
            //film-strip view
            GalleryViewer.loadItem(currentImage);
        } else {
            //thumbnail view
            var currentPage = parseInt(currentImage);

            if (!isNaN(currentPage)) {
                GalleryViewer.loadPage(currentPage);
            }
        }
    } else if (typeof numThumbnailPages != "undefined") { //init thumbnail load for first page
        GalleryViewer.handleLoadPage();
    }
});